#include<stdio.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>

//函数指针类型
typedef (*func_t)();

#define NUM 5
func_t handlers[NUM+1];

//如下是任务
void DownLoad()
{
	printf("我是一个下载的任务...\n");
}
void Flush()
{
	printf("我是一个刷新的任务...\n");
}
void Log()
{
	printf("我是一个记录日志的任务...\n");
}


//注册

void registerHandler(func_t h[],func_t f)
{
	int i=0;
	for(;i<NUM;i++)
	{
		if(h[i]==NULL) break; 
	}

	if(i==NUM) return;
	h[i]=f;
	h[i+1]=NULL;

}

int main()
{
	registerHandler(handlers,DownLoad);
	registerHandler(handlers,Flush);
	registerHandler(handlers,Log);

	pid_t id=fork();
	if(id==0)
	{
		//子进程
		int cnt=3;
		while(1)
		{
			sleep(3);
			printf("我是一个子进程，pid: %d,ppid: %d\n",getpid(),getppid());
			sleep(1);
			cnt--;
			int *p=0;
			*p=100;
		}
		exit(10);
	}

	//父进程
	while(1)
	{
		int status=0;
		pid_t rid=waitpid(id,&status,WNOHANG);
		if(rid>0)
		{
			printf("wait success, rid: %d, exit code: %d,exit signal: %d\n",rid,(status>>8)&0xFF,status&0x7F);//rid
			break;
		}
		else if(rid == 0)
		{
			//函数指针进行回调处理
			int i = 0;
			for(;handlers[i];i++)
			{
				handlers[i]();
			}
			printf("本轮调用结束，子进程没有退出\n");
			sleep(1);
		}
		else
		{
			printf("等待失败\n");
			break;
		}

	}


	//父进程
	//父进程等待失败案例
	//pid_t rid=waitpid(id+1,NULL,0);
	//if(rid > 0)
	//{
	//	printf("wait sucess!rid: %d\n",rid);
	//}
	//else
	//{
	//	printf("wait fail! %d: %s\n",errno,strerror(errno));
	//}
	//
	
	
	//父进程
	//父进程等待成功案例
	//pid_t waitpid(pid_t pid,int *status,int options)//WNOHANG: return immediately if no child has exited ->非阻塞调用 形象示例: 打一次电话就挂，为非阻塞轮询 打电话一直不挂: 为阻塞调用。
	//轮询: 通过循环完成
	//1. >0 :等待结束
	//2. ==0 :调用结束，但子进程没有退出
	//3. <0 : 失败
	
	//非阻塞调用: 可以让等待方，做自己的事情! Non Block
	
	int status=0;
	pid_t rid=waitpid(id,&status,0);
	if(rid > 0)
	{
		if(WIFEXITED(status))
			printf("wait sucess! rid: %d,exit code: %d,exit signal: %d\n",rid,(status>>8)&0xFF,status&0x7F);
		else
			printf("子进程退出异常!\n");
		//printf("wait sucess! rid: %d,exit code: %d,exit signal: %d\n",rid,WEXITSTATUS(status),status&0x7F);
	}
	else
	{
		printf("wait failed! %d: %s\n",errno,strerror(errno));
	}

	sleep(10);

	//父进程
	//1.子进程未退出？？？父进程会阻塞在wait(),直至等至子进程成功退出。
	
	//pid_t rid=wait(NULL);
	//if(rid > 0)
	//{
	//	printf("wait sucess.rid: %d\n",rid);
	//}

	return 0;
}




//void fun()
//{
//	printf("fun begin!\n");
//	//exit(40);//任何地方调用exit，表示进程结束并返回父进程bash，子进程的退出码，C语言提供的库函数
//	_exit(4);//系统调用
//	printf("fun end!\n");
//}

//exit vs _exit
//进程如果exit退出的时候，exit()会进行缓冲区更新
//进程如果_exit退出的时候，_exit()不会进行缓冲区更新


//int main()
//{
	//fun();
	//	printf("main!");

	//sleep(2);

	//_exit(23);

	//int a=10;

	//a/=0;

	//return 89;//进程出现异常，进程退出码无意义，进程收到信号
//	int i=0;
//	for(;i<200;i++)
//	{
//
//		printf("%d->%s\n",i,strerror(i));
//	}
//
//	//printf("hello world\n");
//
//	FILE *fp=fopen("log.txt","r");
//	if(fp==NULL) return errno;
//
//
//	//读取
//	fclose(fp);
//	return 0;
//}
